package cn.jinjimi.domain.data.imp;

import android.net.Uri;

import com.facebook.drawee.backends.pipeline.Fresco;
import com.facebook.imagepipeline.request.ImageRequest;
import com.facebook.imagepipeline.request.ImageRequestBuilder;
import cn.jinjimi.base.preference.PreferenceManager;
import cn.jinjimi.base.util.AndroidUtils;
import cn.jinjimi.base.util.DateUtils;
import cn.jinjimi.base.util.GsonUtils;
import cn.jinjimi.base.util.LogUtil;
import cn.jinjimi.base.util.StringUtils;
import cn.jinjimi.app.AccountManager;
import cn.jinjimi.app.controller.AppConfigureController;
import cn.jinjimi.app.controller.event.ActivityInfoEvent;
import cn.jinjimi.app.controller.event.ActivityListEvent;
import cn.jinjimi.app.controller.event.AreaEvent;
import cn.jinjimi.app.controller.event.CityEvent;
import cn.jinjimi.app.controller.event.ProductEvent;
import cn.jinjimi.app.controller.event.UpdateModuleConfigEvent;
import cn.jinjimi.domain.data.Store;
import cn.jinjimi.domain.data.net.API;
import cn.jinjimi.domain.data.net.AppService;
import cn.jinjimi.domain.data.net.ProductService;
import cn.jinjimi.domain.data.net.UserService;
import cn.jinjimi.domain.data.dto.ActivityInfoDTO;
import cn.jinjimi.domain.data.dto.AppConfigsDTO;
import cn.jinjimi.domain.data.dto.DynamicDTO;
import cn.jinjimi.domain.data.dto.HeadLineDTO;
import cn.jinjimi.domain.data.dto.InfoModulesDTO;
import cn.jinjimi.domain.data.dto.MaterialDTO;
import cn.jinjimi.domain.data.dto.NoticeDto;
import cn.jinjimi.domain.data.dto.PlanProductDTO;
import cn.jinjimi.domain.data.dto.ProductDTO;
import cn.jinjimi.domain.store.ConfigStore;
import cn.jinjimi.app.entity.Account;
import cn.jinjimi.app.entity.ActivityInfo;
import cn.jinjimi.app.entity.AppConfig.AppAnalySettings;
import cn.jinjimi.app.entity.AppConfig.AppConfigs;
import cn.jinjimi.app.entity.AppConfig.AppModule;
import cn.jinjimi.app.entity.AppConfig.AppStartPic;
import cn.jinjimi.app.entity.Area;
import cn.jinjimi.app.entity.Dynamic;
import cn.jinjimi.app.entity.Products;
import cn.jinjimi.app.managers.GuideManager;
import cn.jinjimi.app.store.dao.CacheDao;
import cn.jinjimi.app.bean.SharePrefKeys;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import okhttp3.Headers;
import okhttp3.ResponseBody;
import retrofit2.Response;

/**
 * Created by zhenhua on 16/7/15.
 * <p>
 * TODO 将动态的接口转移到专属类进行管理
 */
public class ConfigStoreImp extends Store implements ConfigStore {

    @Override
    public AppConfigs get() throws IOException {
        return fetchConfigs();
    }

    @Override
    public AppModule get(String url) throws IOException, JSONException {
        return fetchConfigsOfURL(url);
    }

    @Override
    public void save(AppConfigsDTO.AppConfig data) {

    }

    @Override
    public AppConfigs fetchConfigs() throws IOException {

        Response<AppConfigsDTO> response = API.create(AppService.class).getConfigs().execute();

        if (response != null && response.isSuccessful()) {
            AppConfigsDTO dto = response.body();
            if (dto != null && dto.data != null) {
                AppConfigs configs = AppConfigs.insertOrUpdate(dto.data);
                updateAppConfigs(configs);
                return configs;
            }
        }
        return null;
    }

    @Override
    public AppModule fetchConfigsOfURL(String url) throws IOException, JSONException {

        Response<ResponseBody> response = API.create(AppService.class).getConfig(url).execute();

        if (response != null && response.isSuccessful()) {
            try {
                AppModule module = AppModule.insertByStr(response.body().string());
                if (module != null) {
                    updateModule(module, false);
                    return module;
                }
            } catch (JSONException e) {
                LogUtil.print(e);
            }
        }

        return null;
    }

    @Override
    public AppModule fetchConfigOfModule(String name) throws Exception {

        Response<ResponseBody> response = API.create(AppService.class).getConfigOfModule(name).execute();
        if (response != null && response.isSuccessful()) {
            AppModule module = AppModule.insertByStr(response.body().string());
            if (module != null) {
                updateModule(module, false);
                return module;
            }
        }
        return null;
    }

    @Override
    public InfoModulesDTO fetchDynamicMeMenu() throws IOException {
        Response<InfoModulesDTO> response = API.create(AppService.class).getMenus().execute();
        return getResponse(response, InfoModulesDTO.class, true,
                false, CacheDao.MEDYNAMICMENU);
    }

    @Override
    public Area fetchAreaList() throws IOException {
        Response<Area> response = API.create(UserService.class).getProvinces().execute();
        return parseDataAndDispatchEvents(response, new AreaEvent());
    }

    @Override
    public Area fetchCities(String provinceId) throws IOException {
        Response<Area> response = API.create(UserService.class).getCitiesOfProvince(provinceId).execute();
        return parseDataAndDispatchEvents(response, new CityEvent());
    }

    @Override
    public List<Products> getProducts() throws IOException {

        Response<ProductDTO> response = API.create(ProductService.class).getProducts().execute();
        ProductDTO dto = parseDataAndDispatchEvents(response, new ProductEvent());
        return dto == null ? null : dto.getProducts();
    }

    @Override
    public List<ActivityInfo> getActivities() throws IOException {
        Response<ActivityInfoDTO> response = API.create(AppService.class).getActivities().execute();
        ActivityInfoDTO dto = parseDataAndDispatchEvents(response, new ActivityListEvent());
        return dto == null ? null : dto.data;
    }

    @Override
    public HeadLineDTO getHomeHeadLine() throws IOException {
        Response<HeadLineDTO> response = API.create(AppService.class).getHomeHeadLine().execute();
        return getResponse(response);
    }

    @Override
    public DynamicDTO getHomeDynamics() throws IOException {
        DynamicDTO dto = null;
        try {
            Response<DynamicDTO> response = API.create(AppService.class).getHomeDynamics().execute();
            dto = getResponse(response, DynamicDTO.class, true, false, CacheDao.HOMEDYNAMICCACHE);
        } catch (Exception e) {
            e.printStackTrace();
        }
        List<Dynamic> dynamics = new ArrayList<>();

        if (dto == null) {
            //faulted
            Dynamic dynamic = new Dynamic();
            dynamic.title = "数据获取失败，请下拉刷新重试";
            dynamic.linkUrl = "retry";
            dynamics.add(dynamic);
            dto = new DynamicDTO();
        } else if (dto.data != null && !dto.data.isEmpty()) {
            //success
            long currentTime = System.currentTimeMillis();
            for (Dynamic dynamic : dto.data) {
                if (dynamic == null || dynamic.startTime > currentTime || dynamic.endTime < currentTime)
                    continue;
                dynamics.add(dynamic);
            }
        }

        //empty
        if (dynamics.isEmpty()) {
            Dynamic dynamic = new Dynamic();
            dynamic.title = "邀请获利（拿10%推广提成）";
            dynamic.linkUrl = "https://bxr.im/events/html/2016/app_invited/html/main.html";
            dynamics.add(dynamic);
        }

        dto.data = dynamics;
        return dto;
    }

    @Override
    public ActivityInfo getActivityInfo(final ActivityInfo activityInfo) throws IOException {
        String url = activityInfo.state;
        Map<String, String> param = new HashMap<>();
        Account account = AccountManager.getInstance().getAccount();
        param.put("sso_id", account.ssoid);
        param.put("token", account.token);
        Response<ActivityInfo> response = API.create(AppService.class)
                .getActivityInfo(url, param).execute();
        if (response != null && response.isSuccessful()) {
            ActivityInfo data = response.body();
            if (data != null && data.data != null) {
                activityInfo.data = data.data;
                success(ActivityInfoEvent.class, activityInfo);
                return data;
            }
        }

        fail(ActivityInfoEvent.class);
        return null;
    }

    @Override
    public NoticeDto getNoticeList() throws IOException {

        String update_time = PreferenceManager.getStringData(SharePrefKeys.PREF_NOTICE_LAST_MODIFY + AccountManager.getInstance().getAccount().ssoid);

        Response<NoticeDto> resp = API.create(AppService.class).getNotices(update_time).execute();
        if (resp.isSuccessful()) {
            Headers headers = resp.headers();
            String lastModifyTime = headers.get("Last-Modified");
            resp.body().lastModifyTime = lastModifyTime;
        }

        return resp.isSuccessful() ? resp.body() : null;

    }

    @Override
    public MaterialDTO getAppMaterials() throws IOException {
        return getResponse(API.create(AppService.class).getAppMaterials().execute(),
                MaterialDTO.class,
                true,
                false,
                CacheDao.HOMEMATERIALCACHE);
    }

    @Override
    public PlanProductDTO getPlanProducts(int companyId) throws IOException {
        Response<PlanProductDTO> respose = API.create(AppService.class).getPlanProducts(companyId).execute();
        return getResponse(respose, PlanProductDTO.class, true, false, CacheDao.HOMEPLANCACHE + companyId);
    }

    @Override
    public void updateAppConfigs(AppConfigs appConfigs) {
        try {
            if (appConfigs.moduleGlobal != null) {

                PreferenceManager.setData(SharePrefKeys.PREF_MODULE_GLOBAL, GsonUtils.toJson(appConfigs.moduleGlobal));

                JSONObject jsonObject = new JSONObject(appConfigs.moduleGlobal.config);
                Iterator<String> keys = jsonObject.keys();

                //将全局配置降解为全局模块配置；
                //这会导致global.config[.moduleA]配置项目会被 modules[].[moduleA]覆盖；
                while (keys.hasNext()) {
                    AppModule module = new AppModule();
                    module.name = keys.next();
                    module.config = jsonObject.optString(module.name);
                    updateModule(module, false);
                }

            }

            for (AppModule appModule : appConfigs.appModules) {
                updateModule(appModule, true);
            }

        } catch (JSONException e) {
            e.printStackTrace();
        }
    }


    /**
     * 根据模块名称获取配置项目
     *
     * @param name
     * @return
     */
    @Override
    public String getConfig(final String name) {
        return PreferenceManager.getStringData(SharePrefKeys.PREF_MODULE_CONFIG_PREFIX + name);
    }


    /**
     * 更新模块的配置数据
     *
     * @param appModule
     * @param getConfig
     * @throws JSONException
     */
    public void updateModule(AppModule appModule, boolean getConfig) throws JSONException {
        if (appModule == null)
            return;

        if (StringUtils.isEmpty(appModule.config) && StringUtils.isNotEmpty(appModule.link) && getConfig) {
            AppConfigureController.getConfigModule(appModule.link);
            return;
        }

        if (StringUtils.isEmpty(appModule.config) || StringUtils.isEmpty(appModule.name))
            return;

        if (appModule.name.equals(AppModule.ModuleTabs)) { // 首页tabBar
            if (appModule.config != null) {
                PreferenceManager.setData(SharePrefKeys.PREF_MAIN_TAB_JSON_STRING, appModule.config);
            }
        } else if (appModule.name.equals(AppModule.ModuleToolbars)) { // 首页ToolBar
            if (appModule.config != null) {
                PreferenceManager.setData(SharePrefKeys.PREF_HOME_TOOLS_JSON_STRING, appModule.config);
            }
        } else if (appModule.name.equals(AppModule.ModuleHome)) { //首页3.1.1新增广告位
            PreferenceManager.setData(SharePrefKeys.PREF_HOME_NEW_ADV_STRING, appModule.config);
        } else if (appModule.name.equals(AppModule.ModuleSettings)) { // 处理统计设置
            if (appModule.config != null) {
                AppAnalySettings.handleAppSettings(GsonUtils.fromJson(appModule.config, AppAnalySettings.class));
            }
        } else if (appModule.name.equals(AppModule.ModulePoster)) { //海报模块
            if (appModule.config != null) {
                PreferenceManager.setData(SharePrefKeys.PREF_POSTER_CONFIG, appModule.config);
            }
        } else if (appModule.name.equals(AppModule.ModuleAlert)) {
            if (appModule.config != null) {
                GuideManager.getInstance().setConfig(appModule.config);
            }
        } else if (appModule.name.equals(AppModule.ModuleCRM)) {
            if (appModule.config != null) {
                PreferenceManager.setData(SharePrefKeys.PREF_CUSTOMERS_CONFIG, appModule.config);
            }
        } else if (appModule.name.equals(AppModule.ModuleStudyIdea)) {
            if (appModule.config != null) {
                PreferenceManager.setData(SharePrefKeys.PREF_READER_IDEA_CONFIG, appModule.config);
            }
        } else { //其他配置项目
            if (appModule.config != null)
                PreferenceManager.setData(SharePrefKeys.PREF_MODULE_CONFIG_PREFIX + appModule.name, appModule.config);
        }

        dispatch(new UpdateModuleConfigEvent(appModule));
    }

    private void saveStartPic(JSONObject jsonObject) {
        if (jsonObject == null)
            return;

        String current = jsonObject.optString("current");
        String next = jsonObject.optString("next");

        PreferenceManager.setData(SharePrefKeys.PREF_START_PIC_CURRENT, current);
        PreferenceManager.setData(SharePrefKeys.PREF_START_PIC_NEXT, next);

        /* 缓存下一张图片 */
        if (StringUtils.isNotEmpty(next)) {
            AppStartPic tomoPic = GsonUtils.fromJson(next, AppStartPic.class);
            if (tomoPic != null) {
                ImageRequest request = ImageRequestBuilder.newBuilderWithSource(Uri.parse(tomoPic.getFile_url() + getDisPlayStr())).build();
                Fresco.getImagePipeline().prefetchToDiskCache(request, this);
            }
        }
    }

    @Override
    public AppStartPic getStartPic() {
        /* 首先获取current的数据 */
        String currentJson = PreferenceManager.getStringData(SharePrefKeys.PREF_START_PIC_CURRENT);
        String netJson = PreferenceManager.getStringData(SharePrefKeys.PREF_START_PIC_NEXT);

        if (StringUtils.isNotEmpty(currentJson)) {
            AppStartPic temp = GsonUtils.fromJson(currentJson, AppStartPic.class);
            if (temp != null && DateUtils.isToday(temp.getStart_time())) {
                temp.setFile_url(temp.getFile_url() + getDisPlayStr());
                return temp;
            }
        }

        if (StringUtils.isNotEmpty(netJson)) {
            AppStartPic temp = GsonUtils.fromJson(netJson, AppStartPic.class);
            if (temp != null && DateUtils.isToday(temp.getStart_time())) {
                temp.setFile_url(temp.getFile_url() + getDisPlayStr());
                return temp;
            }
        }

        return new AppStartPic();
    }

    public static String getDisPlayStr() {
        int[] screenSize = AndroidUtils.getScreeSize();
        return screenSize[0] + "x" + screenSize[1];
    }

}